// Magic Software, Inc.
// http://www.magic-software.com
// Copyright (c) 2000, All Rights Reserved
//
// Source code from Magic Software is supplied under the terms of a license
// agreement and may not be copied or disclosed except in accordance with the
// terms of that agreement.  The various license agreements may be found at
// the Magic Software web site.  This file is subject to the license
//
// FREE SOURCE CODE
// http://www.magic-software.com/License/free.pdf

#include "MgcCubicPolynomialCurve3.h"

//----------------------------------------------------------------------------
MgcCubicPolynomialCurve3::MgcCubicPolynomialCurve3 (MgcPolynomial* pkXPoly,
    MgcPolynomial* pkYPoly, MgcPolynomial* pkZPoly)
    :
    MgcPolynomialCurve3(pkXPoly,pkYPoly,pkZPoly)
{
    assert( pkXPoly && pkYPoly && pkZPoly );
    assert( pkXPoly->GetDegree() == 3 && pkYPoly->GetDegree() == 3
        &&  pkZPoly->GetDegree() == 3 );

    m_uiVertexQuantity = 0;
    m_akVertex = 0;
}
//----------------------------------------------------------------------------
MgcCubicPolynomialCurve3::~MgcCubicPolynomialCurve3 ()
{
    delete[] m_akVertex;
}
//----------------------------------------------------------------------------
void MgcCubicPolynomialCurve3::Tessellate (unsigned int uiLevel)
{
    // vertices V = (2^L+1)
    unsigned int uiTwoPowL = (1 << uiLevel);
    m_uiVertexQuantity = uiTwoPowL + 1;
    delete[] m_akVertex;
    m_akVertex = new MgcVector3[m_uiVertexQuantity];

    // indices of endpoints, I[t]
    IntervalParameters kIP;
    kIP.m_uiI0 = 0;
    kIP.m_uiI1 = uiTwoPowL;

    // vertices for subdivision
    MgcVector3* akX = m_akVertex;
    akX[kIP.m_uiI0] = GetPosition(m_fTMin);
    akX[kIP.m_uiI1] = GetPosition(m_fTMax);

    // recursive subdivision
    if ( uiLevel > 0 )
    {
        kIP.m_akXuu[0] = GetSecondDerivative(m_fTMin);
        kIP.m_akXuu[1] = GetSecondDerivative(m_fTMax);

        Subdivide(--uiLevel,0.25,akX,kIP);
    }
}
//----------------------------------------------------------------------------
void MgcCubicPolynomialCurve3::Subdivide (unsigned int uiLevel, MgcReal fDSqr,
    MgcVector3* akX, IntervalParameters& rkIP)
{
    // subdivision index
    unsigned int uiIM = (rkIP.m_uiI0 + rkIP.m_uiI1) >> 1;

    // vertices
    MgcVector3 kXuuM = 0.5*(rkIP.m_akXuu[0] + rkIP.m_akXuu[1]);
    akX[uiIM] = 0.5*(akX[rkIP.m_uiI0] + akX[rkIP.m_uiI1] - fDSqr*kXuuM);

    // recurse on two children
    if ( uiLevel > 0 )
    {
        uiLevel--;
        fDSqr *= 0.25;

        IntervalParameters kSubIP;

        // subinterval [t0,tM]
        kSubIP.m_uiI0 = rkIP.m_uiI0;
        kSubIP.m_uiI1 = uiIM;
        kSubIP.m_akXuu[0] = rkIP.m_akXuu[0];
        kSubIP.m_akXuu[1] = kXuuM;
        Subdivide(uiLevel,fDSqr,akX,kSubIP);

        // subinterval [tM,t1]
        kSubIP.m_uiI0 = uiIM;
        kSubIP.m_uiI1 = rkIP.m_uiI1;
        kSubIP.m_akXuu[0] = kXuuM;
        kSubIP.m_akXuu[1] = rkIP.m_akXuu[1];
        Subdivide(uiLevel,fDSqr,akX,kSubIP);
    }
}
//----------------------------------------------------------------------------
